package com.pe.pgn.clubpgn.dao.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.pe.pgn.clubpgn.common.CLPConstantes;
import com.pe.pgn.clubpgn.dao.TarjetaPersonaDao;
import com.pe.pgn.clubpgn.dao.hibernate.GenericDaoHibernate;
import com.pe.pgn.clubpgn.domain.ClpbTarjetaPersona;
import com.pe.pgn.clubpgn.domain.ClpdTipoTarjetaPersona;
import com.pe.pgn.clubpgn.domain.beans.BNTarjetaPersona;
import com.pe.pgn.clubpgn.util.StringUtil;
import com.pe.pgn.clubpgn.webapp.util.CalendarUtil;

@Repository("tarjetaPersonaDao")
public class TarjetaPersonaDaoImpl extends GenericDaoHibernate<ClpbTarjetaPersona, Long>  implements
		TarjetaPersonaDao {
		
	private JdbcTemplate jdbcTemplate;
	
	public TarjetaPersonaDaoImpl() {
		super(ClpbTarjetaPersona.class);
	}
	
	@Autowired
	public void setDataSource(DataSource dataSource) {
		this.jdbcTemplate = new JdbcTemplate(dataSource);
	}
	
	@SuppressWarnings({ "unchecked"})
	public List<ClpbTarjetaPersona> obtenerTarjetasPersonas(){

		StringBuffer query = new StringBuffer();
		query.append(" select * from (");		
		query.append(" 	select tp.id                                           as id                    ,");
		query.append("  	tp.co_codigo_tarjeta_persona                       as coCodigoTarjetaPersona,");
		query.append(" 		to_char(tp.da_fecha_inicio_vigencia, 'dd/MM/yyyy') as desFechaInicio ,");
		query.append("  	to_char(tp.da_fecha_fin_vigencia, 'dd/MM/yyyy')    as desFechaFin    ,");
		query.append("  	cp.de_nombre || ' ' || cp.de_ape_paterno || ' ' || cp.de_ape_materno  as deNombre  ,");
		query.append("  	e.de_estacion                                      as deEstacion            ,");
		query.append("  	tp.st_tarjeta_persona                              as stStrTarjetaPersona, 	");
		query.append("  	tdp.de_tipo_documento_persona 					   as deTipoDocumentoPersona,");
		query.append("  	cp.co_code_numero_documento 					   as coCodeNumeroDocumento, ");
		query.append("  	to_char(tp.da_fecha_anulacion, 'dd/MM/yyyy') 	   as desFechaAnulacion  ");		
		query.append("   from clpb_tarjeta_persona tp left outer join clpb_cliente_persona cp on tp.co_cliente_persona = cp.id");
		query.append("       left outer join clpb_estacion e     on tp.co_estacion   = e.id");
		query.append("       left outer join clpb_tipo_documento_persona tdp on cp.co_tipo_documento = tdp.id");
		query.append("   order by tp.id desc ");
		query.append(" ) where rownum <= ").append(CLPConstantes.MAXIMO_RESULTADO_INICIAL);
		
		List<ClpbTarjetaPersona> list = findListOfBeans(query.toString(), null, ClpbTarjetaPersona.class);
		return list;
	}
			
	public void guardarGrupoTarjetasPersonas(BNTarjetaPersona tarjetaPersona) {

		BigDecimal inicio = tarjetaPersona.getNumeroInicio();
		BigDecimal fin = tarjetaPersona.getNumeroFin();
		
		ClpdTipoTarjetaPersona tipoTarjetaPersona = new ClpdTipoTarjetaPersona();
		tipoTarjetaPersona.setId(tarjetaPersona.getCoTipoTarjetaPersona());
		
		List<ClpbTarjetaPersona> tarjetas = new ArrayList<ClpbTarjetaPersona>();
		
		while (inicio.compareTo(fin) <= 0){

			String codigo =  StringUtil.getStringLeftPad(inicio.toString(), CLPConstantes.LONGITUD_MAXIMA_NUMERO_TARJETA, 
					CLPConstantes.CODIGO_RELLENO_TARJETA_PERSONA, CLPConstantes.PREFIJO_TARJETA_PERSONA);
			
			ClpbTarjetaPersona tarjeta= new ClpbTarjetaPersona();			
			tarjeta.setCoCodigoTarjetaPersona(codigo);
			tarjeta.setClpdTipoTarjetaPersona(tipoTarjetaPersona);
			tarjeta.setDaFechaInicioVigencia(tarjetaPersona.getDaFechaInicioVigencia());
			tarjeta.setDaFechaFinVigencia(tarjetaPersona.getDaFechaFinVigencia());
			tarjeta.setDeObservaciones(tarjetaPersona.getDeObservaciones());
			tarjeta.setStTarjetaPersona(Boolean.FALSE);
			
			inicio = inicio.add(BigDecimal.ONE);
			asignarCamposAutoriaATarjetaPersona(tarjeta);
			tarjetas.add(tarjeta);
		}
		getHibernateTemplate().saveOrUpdateAll(tarjetas);
		getHibernateTemplate().flush();
	}
	
	public boolean existeRango(BNTarjetaPersona tarjetaPersona){

		StringBuffer query = new StringBuffer();
		query.append("select count(*) ");
		query.append("	from clpb_tarjeta_persona ");
		query.append("	where to_number(substr(co_codigo_tarjeta_persona, 2)) between ").append(tarjetaPersona.getNumeroInicio());
		query.append("		and ").append(tarjetaPersona.getNumeroFin());

		int count = jdbcTemplate.queryForInt(query.toString());
        
		if(count > 0){
			return true;
		}
		return false;
	}
	
	public BigDecimal obtenerMaximoCodigoTarjetaPersona() {
		
		StringBuilder sql = new StringBuilder();		
		sql.append(" select max(to_number(substr(co_codigo_tarjeta_persona, 2))) " );
		sql.append(" from clpb_tarjeta_persona  ");
		
		BigDecimal codigoMaximo = jdbcTemplate.queryForObject(sql.toString(), BigDecimal.class);
		if(codigoMaximo == null){
			return BigDecimal.ZERO;
		}
		
		return codigoMaximo;
	}	
	
	public List<String> obtenerListaTarjetaNoAsignadas(){
		
		StringBuffer query = new StringBuffer();
		query.append("select co_codigo_tarjeta_persona as coCodigoTarjetaPersona ");
		query.append("	from clpb_tarjeta_persona ");
		query.append("	where co_cliente_persona is null ");
		query.append("		and co_estacion is null ");
		query.append("		and st_tarjeta_persona = '").append(CLPConstantes.ST_FALSO).append("' ");
		query.append("	order by co_codigo_tarjeta_persona asc ");
		
		List<String> listaCodigos = jdbcTemplate.queryForList(query.toString(),String.class);
		return listaCodigos;
	}
	
	public boolean existenCodigosAsignadosEnRango(BNTarjetaPersona tarjetaPersona){
		
		StringBuffer query = new StringBuffer();
		query.append("select count(*) as codigo   ");
		query.append("	from clpb_tarjeta_persona  ");
		query.append("	where to_number(substr(co_codigo_tarjeta_persona, 2)) between ").append(tarjetaPersona.getNumeroInicio());
		query.append("		and ").append(tarjetaPersona.getNumeroFin());
		query.append("		and (co_cliente_persona is not null  ");
		query.append("  		or co_estacion is not null  ");
		query.append("			or st_tarjeta_persona = '").append(CLPConstantes.ST_VERDADERO).append("') ");
		
		int count = jdbcTemplate.queryForInt(query.toString());
		if(count > 0){
			return true;
		}
		return false;
	}
	
	public void asignarTarjetasPersonas(BNTarjetaPersona tarjetaPersona){
		
		StringBuffer query = new StringBuffer();
		query.append("update clpb_tarjeta_persona ");
		query.append("	set co_estacion = ").append(tarjetaPersona.getCoEstacion());
		query.append(",		st_tarjeta_persona = '").append(CLPConstantes.ST_VERDADERO).append("' ");
		
		if(tarjetaPersona.getDaFechaFinVigencia() != null){
			query.append(", da_fecha_fin_vigencia = to_date('")
				.append(CalendarUtil.calendarToString(CLPConstantes.DATE_PATTERN, 
						tarjetaPersona.getDaFechaFinVigencia())).append("', '").append(CLPConstantes.DATE_PATTERN).append("') ");
		}
		
		if(tarjetaPersona.getDaFechaInicioVigencia() != null){
			query.append(", da_fecha_inicio_vigencia = to_date('")
				.append(CalendarUtil.calendarToString(CLPConstantes.DATE_PATTERN, 
						tarjetaPersona.getDaFechaInicioVigencia())).append("', '").append(CLPConstantes.DATE_PATTERN).append("') ");
		}
		
		query.append(", de_observaciones = '").append(tarjetaPersona.getDeObservaciones()).append("' ");
		
		query.append(", co_usuario_modificador = '").append(getUsuarioLogueado().getUsername()).append("' ");
		query.append(", da_fecha_modificacion = SYSDATE ");
		
		String inicio =  StringUtil.getStringLeftPad(tarjetaPersona.getNumeroInicio().toString(),
				CLPConstantes.LONGITUD_MAXIMA_NUMERO_TARJETA, CLPConstantes.CODIGO_RELLENO_TARJETA_PERSONA, 
				CLPConstantes.PREFIJO_TARJETA_PERSONA);
		String fin = StringUtil.getStringLeftPad(tarjetaPersona.getNumeroFin().toString(), 
				CLPConstantes.LONGITUD_MAXIMA_NUMERO_TARJETA, CLPConstantes.CODIGO_RELLENO_TARJETA_PERSONA, 
				CLPConstantes.PREFIJO_TARJETA_PERSONA);
		
		query.append("	where co_codigo_tarjeta_persona between ").append(inicio);
		query.append("	and ").append(fin);
		
		jdbcTemplate.update(query.toString());
	}	
	
	public ClpbTarjetaPersona obtenerTarjetaPersona(Long id){
		
		ClpbTarjetaPersona tarjetaPersona = get(id);
		return tarjetaPersona;
	}
	
	public void eliminarTarjetaPersona(Long id){
		
		ClpbTarjetaPersona tarjetaPersona = obtenerTarjetaPersona(id);
		tarjetaPersona.setStTarjetaPersona(Boolean.FALSE);
		guardarTarjetaPersona(tarjetaPersona);
	}
	
	public void guardarTarjetaPersona(ClpbTarjetaPersona tarjetaPersona){
		
		asignarCamposAutoriaATarjetaPersona(tarjetaPersona);
		
		save(tarjetaPersona);
		getHibernateTemplate().flush();
	}

	private void asignarCamposAutoriaATarjetaPersona(
			ClpbTarjetaPersona tarjetaPersona) {
		if(tarjetaPersona.getId() == null){
			
			tarjetaPersona.setCoUsuarioCreador(getUsuarioLogueado().getUsername());
			tarjetaPersona.setDaFechaCreacion(Calendar.getInstance());
		}
		else{
			tarjetaPersona.setCoUsuarioModificador(getUsuarioLogueado().getUsername());
			tarjetaPersona.setDaFechaModificacion(Calendar.getInstance());
			
			if(seAsignoEstacion(tarjetaPersona)){
				tarjetaPersona.setStTarjetaPersona(Boolean.TRUE);
			}
		}
	}
	
	public boolean seAsignoEstacion(ClpbTarjetaPersona tarjetaPersona){
		
		StringBuffer query = new StringBuffer();
		query.append("select co_estacion ");
		query.append("	from clpb_tarjeta_persona ");
		query.append("	where id = ").append(tarjetaPersona.getId());
		
		Object object = jdbcTemplate.queryForObject(query.toString(), Object.class);
		if(object != null){
			return false;
		}
		return true;

	}
	
	@SuppressWarnings({ "unchecked"})
	public List<ClpbTarjetaPersona> buscarTarjetas(String coCodigoTarjetaPersona, 
			Long coEstacion, String deNombre, String fechaVigencia, String estadoTarjeta, String stStrAnulada){
		
		StringBuffer query = new StringBuffer();
		
		query.append(" select tp.id                                        	   as id                    ,");
		query.append("  	tp.co_codigo_tarjeta_persona                       as coCodigoTarjetaPersona,");
		query.append(" 		to_char(tp.da_fecha_inicio_vigencia, 'dd/MM/yyyy') as desFechaInicio ,");
		query.append("  	to_char(tp.da_fecha_fin_vigencia, 'dd/MM/yyyy')    as desFechaFin    ,");
		query.append("  	cp.de_nombre || ' ' || cp.de_ape_paterno || ' ' || cp.de_ape_materno  as deNombre  ,");
		query.append("  	e.de_estacion                                      as deEstacion            ,");
		query.append("  	tp.st_tarjeta_persona                              as stStrTarjetaPersona, 	");
		query.append("  	tdp.de_tipo_documento_persona 					   as deTipoDocumentoPersona,");
		query.append("  	cp.co_code_numero_documento 					   as coCodeNumeroDocumento, ");
		query.append("  	to_char(tp.da_fecha_anulacion, 'dd/MM/yyyy') 	   as desFechaAnulacion  ");		
		query.append("   from clpb_tarjeta_persona tp left outer join clpb_cliente_persona cp on tp.co_cliente_persona = cp.id");
		query.append("       left outer join clpb_estacion e     on tp.co_estacion   = e.id");
		query.append("       left outer join clpb_tipo_documento_persona tdp on cp.co_tipo_documento = tdp.id");
	
		query.append("	where 1 = 1 ");
		
		if(StringUtils.isNotBlank(coCodigoTarjetaPersona)){
			query.append("		and tp.co_codigo_tarjeta_persona like '%").append(coCodigoTarjetaPersona).append("%' ");
		}
		
		if(StringUtils.isNotBlank(deNombre)){
			
			String deCliente = "";
			String[] arrayCliente = deNombre.trim().split(" ");
			if(arrayCliente.length > 1){
				for (String strCliente : arrayCliente) {
					deCliente += strCliente+"%";
				}
				
				if(deCliente.endsWith("%")){
					deCliente = deCliente.substring(0, deCliente.length()-1);
				}
			}else{
				deCliente = deNombre.trim();
			}
			
			query.append("		and upper(cp.de_nombre||' '|| cp.de_ape_paterno||' '|| cp.de_ape_materno) like upper('%"+deCliente+"%') ");
		}
		
		if(coEstacion != null && coEstacion.longValue() >= 0){
			query.append("		and tp.co_estacion = ").append(coEstacion);
		}
		
		if(StringUtils.isNotBlank(fechaVigencia)){
			query.append(" 		and to_date('"+fechaVigencia+"','"+CLPConstantes.DATE_PATTERN+"') between to_date(tp.da_fecha_inicio_vigencia,'"+CLPConstantes.DATE_PATTERN+"') and to_date(tp.da_fecha_fin_vigencia,'"+CLPConstantes.DATE_PATTERN+"')");
		}
		
		if(StringUtils.isNotBlank(estadoTarjeta) && !estadoTarjeta.equalsIgnoreCase(CLPConstantes.CARACTER_GUION_NO_ESPACIOS)){
			query.append(" 		and tp.st_tarjeta_persona='"+estadoTarjeta+"'");
		}
		
		if(StringUtils.isNotBlank(stStrAnulada) && !stStrAnulada.equalsIgnoreCase(CLPConstantes.CARACTER_GUION_NO_ESPACIOS)){
			if(stStrAnulada.equals(CLPConstantes.ST_VERDADERO)){
				query.append("  and tp.da_fecha_anulacion is not null  ");
			}else{
				query.append("  and tp.da_fecha_anulacion is null  ");
			}
		}
		
		query.append("   order by tp.id desc ");
		System.out.println(" QUERY "+query.toString());
		
		List<ClpbTarjetaPersona> list = findListOfBeans(query.toString(), null, ClpbTarjetaPersona.class);
		return list;
	}

	public List<String> obtenerListaTarjetaNoAsignadosClientes(Long coEstacion) {

		StringBuffer query = new StringBuffer();
		query.append("select co_codigo_tarjeta_persona as coCodigoTarjetaPersona ");
		query.append("	from clpb_tarjeta_persona ");
		query.append("	where co_cliente_persona is null ");
		query.append("		and da_fecha_anulacion is null ");
		query.append("		and co_estacion = ").append(coEstacion);
		query.append("		and st_tarjeta_persona = '").append(CLPConstantes.ST_VERDADERO).append("' ");
		query.append("	order by co_codigo_tarjeta_persona asc ");
		
		System.out.println("* obtenerListaTarjetaNoAsignadosClientes: "+query.toString());
		List<String> listaCodigos = jdbcTemplate.queryForList(query.toString(),String.class);
		return listaCodigos;
	}

	public void reasignarTarjetasPersonas(BNTarjetaPersona tarjetaPersona) {

		StringBuffer query = new StringBuffer();
		query.append("update clpb_tarjeta_persona ");
		query.append("	set co_estacion = ").append(tarjetaPersona.getCoEstacion());
		query.append(", co_usuario_modificador = '").append(getUsuarioLogueado().getUsername()).append("' ");
		query.append(", da_fecha_modificacion = SYSDATE ");
		
		String inicio =  StringUtil.getStringLeftPad(tarjetaPersona.getNumeroInicio().toString(),
				CLPConstantes.LONGITUD_MAXIMA_NUMERO_TARJETA, CLPConstantes.CODIGO_RELLENO_TARJETA_PERSONA, 
				CLPConstantes.PREFIJO_TARJETA_PERSONA);
		String fin = StringUtil.getStringLeftPad(tarjetaPersona.getNumeroFin().toString(), 
				CLPConstantes.LONGITUD_MAXIMA_NUMERO_TARJETA, CLPConstantes.CODIGO_RELLENO_TARJETA_PERSONA, 
				CLPConstantes.PREFIJO_TARJETA_PERSONA);
		
		query.append("	where co_cliente_persona is null and co_estacion is not null ");
		query.append("	and (co_codigo_tarjeta_persona between ").append(inicio);
		query.append("	and ").append(fin).append(")");
		
		jdbcTemplate.update(query.toString());
	}

	public boolean existenCodigosAsignadosEnRangoPorEstacion(
			BNTarjetaPersona tarjetaPersona) {

		StringBuffer query = new StringBuffer();
		query.append("select count(*) as codigo   ");
		query.append("	from clpb_tarjeta_persona  ");
		query.append("	where to_number(substr(co_codigo_tarjeta_persona, 2)) between ").append(tarjetaPersona.getNumeroInicio());
		query.append("		and ").append(tarjetaPersona.getNumeroFin());
		query.append("		and (co_cliente_persona is not null  ");
		query.append("  		and co_estacion is not null) ");
		
		int count = jdbcTemplate.queryForInt(query.toString());
		if(count > 0){
			return true;
		}
		return false;

	}
}
